home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 May: Tool Chest / Dev.CD May 97 TC.toast / Sample Code / Snippets / Interapplication Communication / SuspendAppleEvent / SuspendEvent.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-09  |  25.3 KB  |  653 lines  |  [TEXT/MPS ]

  1. /* SuspendEvent */
  2. /* A simple example of suspending and resuming an AppleEvent */
  3. /* Written by C.K. Haun <TR> */
  4. /* Apple Developer Tech Support */
  5. /* Of course, Copyright 1991-1992, Apple Computer Inc. */
  6.  
  7. #include "SuspendEvent.h"
  8.  
  9. /* prototypes */
  10. void InitalizeApp(void);
  11. void DoDiskEvents(long dinfo);                              /* hi word is error code, lo word is drive number */
  12. void DrawMain(WindowPtr drawIt);
  13. Boolean DoSelected(long val);
  14. void SizeMain(WindowPtr theWindow);
  15. void InitAEStuff(void);
  16. void DoHighLevel(EventRecord *AERecord);
  17. void DoDaCall(MenuHandle themenu, long theit);
  18. void DoDocumentClick(WindowPtr theWindow);
  19. OSErr modfiedProcessOpenPrint(AppleEvent *messagein, AppleEvent *theReply, Boolean printIt);
  20. pascal OSErr AEOpenHandler(AppleEvent *messagein, AppleEvent *reply, long refIn);
  21. pascal OSErr AEOpenDocHandler(AppleEvent *messagein, AppleEvent *reply, long refIn);
  22. pascal OSErr AEPrintHandler(AppleEvent *messagein, AppleEvent *reply, long refIn);
  23. pascal OSErr AEQuitHandler(AppleEvent *messagein, AppleEvent *reply, long refIn);
  24. void SampleHelpDialog(void);
  25. WindowPtr AddNewWindow(short theID);
  26. void InvalAll(void);
  27. void NilProc(void);
  28. /* one external */
  29. extern void _DataInit();                                    /* this is the C initialization code */
  30.  
  31. /* globals */
  32. Boolean gQuit, gInBackground;
  33. unsigned long gMySleep;
  34. ProcessSerialNumber gOurSN;
  35. short gHelpItem;
  36.  
  37. /* globals for event suspension */
  38. Boolean eventIsPending;
  39. AEDesc theSuspEvent, theSuspReply;
  40.  
  41. #pragma segment Main
  42. main()
  43. {
  44.     EventRecord myEventRecord;
  45.     WindowPtr twindow;
  46.     short fHit;
  47.     windowCHandle tempWCH;
  48.     
  49.     UnloadSeg((Ptr)_DataInit);                              /* throw out setup code */
  50.     InitalizeApp();
  51.     UnloadSeg((Ptr)InitalizeApp);                           /* get rid of my initialization code */
  52.     do {
  53.         
  54.         WaitNextEvent(everyEvent, &myEventRecord, gMySleep, nil);
  55.         switch (myEventRecord.what) {
  56.             case nullEvent:
  57.                 /* no nul processing in this sample */
  58.                 break;
  59.             case updateEvt:
  60.                 /* always check to see if it's my window */
  61.                 /* this may not seem necessary under 7.0, where it's unlikely or impossible for */
  62.                 /* a DA to be in your layer, but there are others */
  63.                 /* who can stick themselves into your window list, */
  64.                 /* BalloonWriter comes quickly to mind */
  65.                 if (((WindowPeek)myEventRecord.message)->windowKind == kMyDocumentWindow) {
  66.                     tempWCH = (windowCHandle)GetWRefCon((WindowPtr)myEventRecord.message);
  67.                     if (tempWCH)
  68.                         (ProcPtr)((*tempWCH)->drawMe)((WindowPtr)myEventRecord.message);
  69.                 }
  70.                 break;
  71.             case mouseDown:
  72.                 /* first see where the hit was */
  73.                 fHit = FindWindow(myEventRecord.where, &twindow);
  74.                 switch (fHit) {
  75.                     Rect limitRect;
  76.                     Str255 tempString;
  77.                     long back;
  78.                     case inDesk:                            /* if they hit in desk, then the process manager */
  79.                         break;                              /* will switch us out, we don't need to do anything */
  80.                     case inMenuBar:
  81.                         DoSelected(MenuSelect(myEventRecord.where));
  82.                         break;
  83.                         
  84.                     case inSysWindow:
  85.                         /* pass to the system */
  86.                         SystemClick(&myEventRecord, twindow);
  87.                         break;
  88.                     case inContent:
  89.                         /* Handle content and control clicks here */
  90.                         if (FrontWindow()) {                /* don't do this unless we have a window open, silly */
  91.                             if (FrontWindow() == twindow && (((WindowPeek)twindow)->windowKind == kMyDocumentWindow)) {
  92.                                 windowCHandle clicker;
  93.                                 clicker = (windowCHandle)GetWRefCon(twindow);
  94.                                 /* jump to the content function stored for this window */
  95.                                 HLock((Handle)clicker);     /* lock it down so things don't get stupid */
  96.                                 (ProcPtr)((*clicker)->clickMe)(twindow);
  97.                                 HUnlock((Handle)clicker);       /* all done */
  98.                             } else {
  99.                                 SelectWindow(twindow);      /* select the window */
  100.                                 SetPort(twindow);
  101.                             }
  102.                         }
  103.                         break;
  104.                     case inDrag:
  105.                         DragWindow(twindow, myEventRecord.where, &qd.screenBits.bounds);
  106.                         break;
  107.                     case inGrow:
  108.                         /* Call GrowWindow here if you have a grow box */
  109.                         SetPort(twindow);
  110.                         limitRect = qd.screenBits.bounds;
  111.                         limitRect.top = kMinHeight;
  112.                         GetWTitle(twindow, tempString);
  113.                         /* I'm not letting the user shrink the window so */
  114.                         /* small that the title is truncated */
  115.                         limitRect.left = StringWidth(tempString) + 120;
  116.                         back = GrowWindow(twindow, myEventRecord.where, &limitRect);
  117.                         
  118.                         if (back) {
  119.                             windowCHandle tempWCH = (windowCHandle)GetWRefCon(twindow);
  120.                             Rect sizeRect = ((WindowPtr)twindow)->portRect;
  121.                             InvalRect(&sizeRect);
  122.                             sizeRect.top = sizeRect.bottom - 16;
  123.                             sizeRect.left = sizeRect.right - 16;
  124.                             EraseRect(&sizeRect);
  125.                             InvalRect(&sizeRect);
  126.                             SizeWindow(twindow, back & 0xffff, back >> 16, true);
  127.                             (ProcPtr)((*tempWCH)->sizeMe)(twindow);
  128.                         }
  129.                         InvalRect(&twindow->portRect);
  130.                         
  131.                         break;
  132.                     case inGoAway:
  133.                         /* Click in Close box */
  134.                         if (TrackGoAway(twindow, myEventRecord.where))
  135.                             (ProcPtr)((*(windowCHandle)((WindowPeek)twindow)->refCon)->closeMe)(twindow);
  136.                         
  137.                         break;
  138.                     case inZoomIn:
  139.                     case inZoomOut:
  140.                         if (TrackBox(twindow, myEventRecord.where, fHit)) {
  141.                             windowCHandle tempWCH = (windowCHandle)GetWRefCon(twindow);
  142.                             SetPort(twindow);
  143.                             
  144.                             ZoomWindow(twindow, fHit, true);
  145.                             InvalRect(&twindow->portRect);
  146.                             (ProcPtr)((*tempWCH)->sizeMe)(twindow);
  147.                         }
  148.                 }
  149.             case mouseUp:
  150.                 /* don't care */
  151.                 break;
  152.                 /* same action for key or auto key */
  153.             case keyDown:
  154.             case autoKey:
  155.                 if (myEventRecord.modifiers & cmdKey)
  156.                     DoSelected(MenuKey(myEventRecord.message & charCodeMask));
  157.                 break;
  158.             case keyUp:
  159.                 /* don't care */
  160.                 break;
  161.             case diskEvt:
  162.                 /* I don't do anything special for disk events, this just passes them */
  163.                 /* to a function that checks for an error on the mount */
  164.                 DoDiskEvents(myEventRecord.message);
  165.                 break;
  166.             case activateEvt:
  167.                 if (myEventRecord.modifiers & activeFlag) {
  168.                     tempWCH = (windowCHandle)GetWRefCon((WindowPtr)myEventRecord.message);
  169.                     (ProcPtr)((*tempWCH)->drawMe)((WindowPtr)myEventRecord.message);
  170.                 }
  171.                 break;
  172.             case networkEvt:
  173.                 /* don't care */
  174.                 break;
  175.             case driverEvt:
  176.                 /* don't care */
  177.                 break;
  178.             case app4Evt:
  179.                 switch ((myEventRecord.message >> 24) & 0x0FF) {        /* high byte of message */
  180.                     case suspendResumeMessage:              /* suspend/resume is also an activate/deactivate */
  181.                         gInBackground = (myEventRecord.message & kResumeMask) == 0;
  182.                         if (gInBackground) {
  183.                             /* nothing for going in the background in this sample */
  184.                         } else {
  185.                             /* make sure the cursor is an arrow when we come forward */
  186.                             InitCursor();
  187.                         }
  188.                         break;
  189.                 }
  190.                 break;
  191.             default:
  192.                 break;
  193.                 /* This dispatches high level events (AppleEvents, for example) */
  194.                 /* to our dispatch routine. This is NEW in the event loop for */
  195.                 /* System 7 */
  196.             case kHighLevelEvent:
  197.                 DoHighLevel(&myEventRecord);
  198.                 break;
  199.                 
  200.         }
  201.     }
  202.             while (gQuit != true);
  203.     
  204. }
  205.  
  206. /* DoDaCall opens the requested DA. It's here as a seperate routine if you'd */
  207. /* like to perform some action or just know when a DA is opened in your */
  208. /* layer. Can be handy to track memory problems when a DA is opened */
  209. /* with an Option-open */
  210. void DoDaCall(MenuHandle themenu, long theit)
  211. {
  212.     long qq;
  213.     char DAname[255];
  214.     GetItem(themenu, theit, &DAname);
  215.     qq = OpenDeskAcc(DAname);
  216. }
  217.  
  218. /* end DoDaCall */
  219.  
  220. /* DoDiskEvents just checks the error code from the disk mount, */
  221. /* and puts up the 'Format' dialog (through DIBadMount) if need be */
  222. /* You can do much more here if you care about what disks are */
  223. /* in the drive */
  224. void DoDiskEvents(long dinfo)                               /* hi word is error code, lo word is drive number */
  225. {
  226.     short hival, loval, tommy;
  227.     Point fredpoint =  {
  228.         40, 40
  229.     };
  230.     hival = HiWord(dinfo);
  231.     loval = LoWord(dinfo);
  232.     if (hival != noErr)                                     /* something happened */ {
  233.         tommy = DIBadMount(fredpoint, dinfo);
  234.     }
  235. }
  236.  
  237. /* draws my window. Pretty simple */
  238. void DrawMain(WindowPtr drawIt)
  239. {
  240.     RgnHandle tempRgn;
  241.     short oldSize = drawIt->txSize;
  242.     Rect scratchRect;
  243.     BeginUpdate(drawIt);
  244.     SetPort(drawIt);
  245.     EraseRect(&drawIt->portRect);
  246.     /* tell folks if an event has been suspendered */
  247.     if (eventIsPending) {
  248.         Str255 tempString;
  249.         MoveTo(10, 40);
  250.         TextFace(bold);
  251.         TextSize(24);
  252.         
  253.         GetIndString(tempString, kGeneralStrings, kPendingWords1);
  254.         DrawString(tempString);
  255.         GetIndString(tempString, kGeneralStrings, kPendingWords2);
  256.         MoveTo(10, 80);
  257.         DrawString(tempString);
  258.         
  259.         TextSize(oldSize);
  260.         TextFace(normal);
  261.     }
  262.     scratchRect = drawIt->portRect;
  263.     scratchRect.top = scratchRect.bottom - 15;
  264.     scratchRect.left = scratchRect.right - 15;
  265.     tempRgn = NewRgn();
  266.     GetClip(tempRgn);
  267.     ClipRect(&scratchRect);
  268.     DrawGrowIcon(drawIt);
  269.     SetClip(tempRgn);
  270.     DisposeRgn(tempRgn);
  271.     
  272.     EndUpdate(drawIt);
  273. }
  274.  
  275. void CloseMyWindow(WindowPtr twindow)
  276. {
  277.     DisposeWindow(twindow);
  278. }
  279.  
  280. /* my menu action taker. It returns a Boolean which I usually ignore, but it */
  281. /* mught be handy someday */
  282. /* Actually, I've been returning that Boolean for 7 years, and */
  283. /* never used it, but Who Knows? */
  284. /* I usually use it in an application to determine if a keystroke was accepted */
  285. /* by a menu or whether it should be passed along to any other key acceptors */
  286. Boolean DoSelected(long val)
  287. {
  288.     short loval, hival;
  289.     Boolean returnVal = false;
  290.     loval = LoWord(val);
  291.     hival = HiWord(val);
  292.     
  293.     switch (hival) {                                        /* switch off the menu number selected */
  294.         case kAppleMenu:                                    /* Apple menu */
  295.             if (loval != 1) {                               /* if this was not About, it's a DA */
  296.                 DoDaCall(GetMHandle(kAppleMenu), loval);
  297.             } else {
  298.                 Alert(kAboutBox, nil);                      /* do about box */
  299.             }
  300.             returnVal = true;
  301.             break;
  302.         case kFileMenu:                                     /* File menu */
  303.             switch (loval) {
  304.                 case kQuitItem:
  305.                     gQuit = true;                           /* only item */
  306.                     returnVal = true;
  307.                     break;
  308.                 default:
  309.                     break;
  310.             }
  311.             break;
  312.         case kEditMenu:
  313.             /* edit menu junk */
  314.             /* don't care */
  315.             switch (loval) {
  316.             default:
  317.                 break;
  318.             }
  319.             break;
  320.         case kToolsMenu:
  321.             /* add all your test stuff here */
  322.             switch (loval) {
  323.             default:
  324.                 break;
  325.             }
  326.             break;
  327.         case kHMHelpMenuID:                                 /* Defined in Balloons.h */
  328.             /* I only care about this item. If anything else is returned here, I don't know what */
  329.             /* it is, so I leave it alone. Remember, the Help Manager chapter says that */
  330.             /* Apple reserves the right to add and change things in the Help menu */
  331.             
  332.             if (loval == gHelpItem)
  333.                 SampleHelpDialog();
  334.             break;
  335.             
  336.     }
  337.     HiliteMenu(0);
  338.     return(returnVal);
  339. }
  340.  
  341. void DoDocumentClick(WindowPtr theWindow)
  342. {
  343.     /* look to see if an event is pending, if so resume the event */
  344.     if (eventIsPending) {
  345.         /* restart the event */
  346.         AEResumeTheCurrentEvent(&theSuspEvent, &theSuspReply, (AEEventHandlerUPP)kAEUseStandardDispatch, 0);
  347.         /* kAEUseStandardDispatch means re-enter the handler from the top. */
  348.         /* You're other option to pass here is kAENoDispatch, which tells the */
  349.         /* AppleEvent manager that this event is FINISHED, clean up memory */
  350.         /* and don't re-dspatch. */
  351.         
  352.     }
  353. }
  354.  
  355.  
  356. #pragma segment Initialize
  357.  
  358. /* InitAEStuff installs my appleevent handlers */
  359. void InitAEStuff(void)
  360. {    
  361.     OSErr aevtErr = noErr;
  362.     long aLong = 0;
  363.     Boolean gHasAppleEvents = false;
  364.     /* Check this machine for AppleEvents.  If they are not here (ie not 7.0)
  365.     *   then we exit */
  366.     gHasAppleEvents = (Gestalt(gestaltAppleEventsAttr, &aLong) == noErr);
  367.     /* The following series of calls installs all our AppleEvent Handlers.
  368.     *   These handlers are added to the application event handler list that 
  369.     *   the AppleEvent manager maintains.  So, whenever an AppleEvent happens
  370.     *   and we call AEProcessEvent, the AppleEvent manager will check our
  371.     *   list of handlers and dispatch to it if there is one.
  372.     */
  373.     if (gHasAppleEvents) {
  374.          aevtErr = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, 
  375.              NewAEEventHandlerProc(AEOpenHandler),0, false);
  376.              if (aevtErr)  ExitToShell();
  377.  
  378.          aevtErr = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, 
  379.              NewAEEventHandlerProc(AEOpenDocHandler),0, false);
  380.              if (aevtErr)  ExitToShell();
  381.  
  382.          aevtErr = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, 
  383.              NewAEEventHandlerProc(AEQuitHandler), 0, false);
  384.              if (aevtErr)  ExitToShell();
  385.  
  386.          aevtErr = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments, 
  387.              NewAEEventHandlerProc(AEPrintHandler),0, false);
  388.              if (aevtErr)  ExitToShell();
  389.          
  390.        } 
  391.     else ExitToShell();
  392.     
  393. }
  394. /* end InitAEStuff */
  395.  
  396. #pragma segment Main
  397.  
  398. /* I'm not doing error handling in this sample for clarities sake, you should. Hah, */
  399. /* easy for me to say, huh? */
  400. void DoHighLevel(EventRecord *AERecord)
  401. {
  402.     OSErr myErr;
  403.     myErr = AEProcessAppleEvent(AERecord);
  404.     
  405. }
  406.  
  407. /* end DoHighLevel */
  408.  
  409. /* This is the standard Open Application event. */
  410. pascal OSErr AEOpenHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  411. {
  412.     WindowPtr myWindow;
  413.  
  414. #pragma unused (messagein,reply,refIn)
  415.     /* we of course don't do anything here in this simple app */
  416.     /* except open our window */
  417.     myWindow = AddNewWindow(kDocWindowResID);
  418.     
  419.     return(noErr);
  420. }
  421.  
  422. /* end AEOpenHandler */
  423.  
  424. /* Open Doc, opens our documents. Remember, this can happen at application start AND */
  425. /* anytime else. If your app is up and running and the user goes to the desktop, hilites one */
  426. /* of your files, and double-clicks or selects Open from the finder File menu this event */
  427. /* handler will get called. Which means you don't do any initialization of globals here, or */
  428. /* anything else except open then doc. */
  429. /* SO-- Do NOT assume that you are at app start time in this */
  430. /* routine, or bad things will surely happen to you. */
  431.  
  432. pascal OSErr AEOpenDocHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  433. {
  434. #pragma unused (refIn)
  435.     return(modfiedProcessOpenPrint(messagein, reply, false));
  436. }
  437.  
  438. pascal OSErr AEPrintHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  439. {                                                           /* no printing handler in yet, so we'll ignore this */
  440.     /* the operation is functionally identical to the ODOC event, with the additon */
  441.     /* of calling your print routine. */
  442. #pragma unused (refIn)
  443.     return(modfiedProcessOpenPrint(messagein, reply, true));
  444. }
  445.  
  446. /* Standard Quit event handler, to handle a Quit event from the Finder, for example. */
  447. /* ••••• DO NOT CALL EXITTOSHELL HERE ••••• or you will never have a happy life. */
  448. /* OK, it's a few months after I wrote that comment, and I've seen a lot of code */
  449. /* come through DTS that calls ExitToShell from quit handlers. Let me explain... */
  450. /* When an AppleEvent Handler is called (like this quit handler) you are ALMOST */
  451. /* 100% in your application world. A5 is right, you can call any toolbox function, */
  452. /* you can call your own routines, everything _seems_ like you are in complete */
  453. /* control. Well, almost but not quite. The routine has been dispatch to from the */
  454. /* AppleEvent Manager's space, so you _must_ return to that at some point! */
  455. /* Which is why you can't call ETS from here. When you call ExitToShell from an */
  456. /* AE Handler, the most likely thing that happens is the FInder quits, and your */
  457. /* application keeps running. Which ain't what you want, y'know? */
  458. /* so, DON'T CALL EXITTOSHELL FROM AN APPLEEVENT HANDLER!!!!!!!!!!!!!! */
  459. /* Any of 'em, not just a quit handler. Just don't do it. */
  460. /* This comment keeps getting longer because people keep doing it STOP IT! */
  461. pascal OSErr AEQuitHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  462. {
  463. #pragma unused (messagein,refIn,reply)
  464.     gQuit = true;
  465.     return(noErr);
  466. }
  467.  
  468. /* This is my sample help dialog. Does not do anything, expand as you need */
  469. void SampleHelpDialog(void)
  470. {
  471.     DialogPtr tdial = GetNewDialog(kSampHelp, nil, (WindowPtr)-1);
  472.     short itemhit = 0;
  473.     while (itemhit != 1) {
  474.         ModalDialog(nil, &itemhit);
  475.     }
  476.     DisposDialog(tdial);
  477. }
  478.  
  479.  
  480. #ifdef powerc
  481.    QDGlobals    qd;
  482. #endif
  483.  
  484.  
  485. #pragma segment Initialize
  486. void InitalizeApp(void)
  487. {
  488.     MenuHandle helpHandle;
  489.     StringHandle helpString;
  490.     short count;
  491.     long vers;
  492.     MaxApplZone();
  493.     InitGraf((Ptr)&qd.thePort);
  494.     InitFonts();
  495.     InitWindows();
  496.     InitMenus();
  497.     TEInit();
  498.     InitDialogs(nil);
  499.     InitCursor();
  500.     /* Check system version */
  501.     Gestalt(gestaltSystemVersion, &vers);
  502.     vers = (vers >> 8) & 0xf;                               /* shift result over and mask out major version number */
  503.     if (vers < 7) {
  504.         StopAlert(kBadSystem, nil);
  505.         ExitToShell();
  506.     }
  507.     InitAEStuff();
  508.     /* set up my menu junk */
  509.     SetMenuBar(GetNewMBar(kMBarID));
  510.     AddResMenu(GetMHandle(kAppleMenu), 'DRVR');
  511.     
  512.     /* now install my Help menu item in the Help Manager's menu */
  513.     HMGetHelpMenuHandle(&helpHandle);                       /* Get the Hlpe menu handle */
  514.     count = CountMItems(helpHandle);                        /* How many items are there? */
  515.     helpString = GetString(kHelpString);                    /* get my help string */
  516.     DetachResource(helpString);                             /* detach it */
  517.     HNoPurge(helpString);
  518.     MoveHHi((Handle)helpString);
  519.     HLock((Handle)helpString);
  520.     InsMenuItem(helpHandle, (Ptr)*helpString, count + 1);       /* insert my item in the Help menu */
  521.     gHelpItem = CountMItems(helpHandle);                    /* The number of the item */
  522.     
  523.     DrawMenuBar();
  524.     GetCurrentProcess(&gOurSN);                             /* Get our process serial number for later use, if needed */
  525.     
  526. }
  527.  
  528.  
  529. #pragma segment Main
  530. WindowPtr AddNewWindow(short theID)
  531. {
  532.     windowCHandle setControls;
  533.     WindowPtr tempWP;
  534.     short cnt = 0;
  535.     tempWP = GetNewWindow(theID, 0, (WindowPtr)-1);         /* get a new window */
  536.     ((WindowPeek)tempWP)->windowKind = kMyDocumentWindow;       /* mark it as my document window */
  537.     setControls = (windowCHandle)NewHandleClear(sizeof(windowControl));     /* add our control structure to it */
  538.     SetWRefCon(tempWP, (long)setControls);                  /* stop stuffing refCon directly <ckh 1.0.3> */
  539.     HLock((Handle)setControls);                             /* lock it down while we fill it*/
  540.     
  541.     /* add pointers to our procedures for drawing, saving, and closing */
  542.     /* This way, all I need is one dispatch point for drawing, closing */
  543.     /* or whatever, I don't have to case off the window kind to go to the */
  544.     /* correct routine. Kinda like object-oriented programming, but I won't */
  545.     /* admit that. */
  546.     (*setControls)->drawMe = (ProcPtr)DrawMain;
  547.     (*setControls)->clickMe = (ProcPtr)DoDocumentClick;
  548.     (*setControls)->sizeMe = (ProcPtr)SizeMain;
  549.     (*setControls)->closeMe = (ProcPtr)CloseMyWindow;
  550.     (*setControls)->generalData = NewHandle(0);
  551.     return(tempWP);
  552. }
  553.  
  554. void SizeMain(WindowPtr theWindow)
  555. {
  556.     WindowPtr tempWP;
  557.     GetPort(&tempWP);
  558.     InvalRect(&theWindow->portRect);
  559.     SetPort(tempWP);
  560. }
  561.  
  562. void NilProc(void)
  563. {
  564.     
  565. }
  566.  
  567. /* modfiedProcessOpenPrint handles ODOC and PDOC events. Both events open a document, one prints it */
  568. /* This one is modified to suspend any event that opens or prints an kAlDocType document */
  569. /* do NOT use this as is in your app! */
  570. OSErr modfiedProcessOpenPrint(AppleEvent *messagein, AppleEvent *theReply, Boolean printIt)
  571. {
  572.     OSErr err = noErr;
  573.     AEDesc theDesc;
  574.     FSSpec theFSS;
  575.     short loopy;
  576.     long numFilesToOpen;
  577.     AEKeyword ignoredKeyWord;
  578.     DescType ignoredType;
  579.     Size ignoredSize;
  580.     FInfo fileInfo;
  581.     Boolean DoSuspend = false;
  582.     err = AEGetParamDesc(messagein, keyDirectObject, typeAEList, &theDesc);
  583.     err |= AECountItems(&theDesc, &numFilesToOpen);
  584.     if (!err) {
  585.         for (loopy = 1; ((loopy <= numFilesToOpen) && (!err)); ++loopy) {
  586.             
  587.             err = AEGetNthPtr(&theDesc, loopy, typeFSS, &ignoredKeyWord, &ignoredType, (Ptr)&theFSS, sizeof(theFSS),
  588.                               &ignoredSize);
  589.             if (err == noErr) {
  590.                 FSpGetFInfo(&theFSS, &fileInfo);
  591.                 /* make sure it's a data file */
  592.                 /* and if this was called for an eventPend, don't reopen the kFredDocType docs */
  593.                 if (fileInfo.fdCreator == kSuspCreator && fileInfo.fdType == kFredDocType && !eventIsPending) {
  594.                     WindowPtr newW = AddNewWindow(kDocWindowResID);
  595.                     if (newW) {
  596.                         SetWTitle(newW, &theFSS.name);
  597.                     }
  598.                 } else {
  599.                     /* here we see if it's an kAlDocType file. If it is, we either ignore it */
  600.                     /* if its not from the resume, or we process it */
  601.                     if (fileInfo.fdCreator == kSuspCreator && fileInfo.fdType == kAlDocType) {
  602.                         if (eventIsPending) {
  603.                             WindowPtr newW = AddNewWindow(kDocWindowResID);
  604.                             if (newW) {
  605.                                 SetWTitle(newW, &theFSS.name);
  606.                             }
  607.                         } else {
  608.                             /* if there is not an event pending, then this is is an Al file */
  609.                             /* from launch, tell ourselves that there is a reason to suspend */
  610.                             DoSuspend = true;
  611.                         }
  612.                     }
  613.                 }
  614.             }
  615.         }                                                   /* for loopy = ... */
  616.     }
  617.     AEDisposeDesc(&theDesc);
  618.     /* determine if this is the first pass, then we should suspend. If not, */
  619.     /* we press on */
  620.     if (eventIsPending) {
  621.         /* clear it and life is back to normal */
  622.         eventIsPending = false;
  623.     } else {
  624.         /* first pass, no kAlDocType files have been opened, suspend the event and set the */
  625.         /* flag. */
  626.         /* Only if an kAlDocType file was passed at all, which is the DoSuspend flag. */
  627.         if (DoSuspend) {
  628.             eventIsPending = true;
  629.             AESuspendTheCurrentEvent(messagein);
  630.             theSuspEvent = *messagein;
  631.             theSuspReply = *theReply;
  632.         }
  633.     }
  634.     InvalAll();
  635.     return(err);
  636. }
  637.  
  638. void InvalAll(void)
  639. {
  640.     WindowPtr nowFront = FrontWindow();
  641.     WindowPtr oldPort;
  642.     GetPort(&oldPort);
  643.     while (nowFront) {
  644.         if (((WindowPeek)nowFront)->visible) {
  645.             SetPort(nowFront);
  646.             InvalRect(&nowFront->portRect);
  647.         }
  648.         nowFront = (WindowPtr)((WindowPeek)nowFront)->nextWindow;
  649.     }
  650.     SetPort(oldPort);
  651.     
  652. }
  653.